package com.basker.pisces.concurrent.counter;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public abstract class AbstractCounterManager implements ICounterManager {
    private String name;
    private final ConcurrentMap<String, ICounter> counterMap = new ConcurrentHashMap<>(16);
    private Set<String> counterKeys = Collections.emptySet();

    public AbstractCounterManager(String name) {
        this.name = name;
    }

    @Override
    public ICounter getCounter(String key) {
        ICounter counter = this.counterMap.get(key);
        if (counter != null) {
            return counter;
        } else {
            synchronized (this.counterMap) {
                counter = this.counterMap.get(key);

                if (counter == null) {
                    counter = createCounter(key);
                    if (counter != null) {
                        this.counterMap.put(key, counter);
                        updateCounterKeys(key);
                    }
                }
                return counter;
            }
        }
    }

    @Override
    public Collection<String> getCounterKeys() {
        return this.counterKeys;
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected abstract ICounter createCounter(String key);

    protected ConcurrentMap<String, ICounter> getCounterMap() {
        return counterMap;
    }

    private void updateCounterKeys(String key) {
        Set<String> counter = new LinkedHashSet<>(this.counterKeys.size() + 1);
        counter.addAll(this.counterKeys);
        counter.add(key);
        this.counterKeys = Collections.unmodifiableSet(counter);
    }
}
